package vue.panneau2.modele.util;
import java.util.ArrayList;

import vue.panneau2.modele.exception.IndiceIncorrectException;
import vue.panneau2.modele.exception.MauvaiseDimensionException;

/**
 * Test d'equation generique (Dimension N)
 */
public class Equation {
	// les equations sous forme de fractions
	private ArrayList<Float> coefficients = new ArrayList<Float>();
	private int signe = INF_OU_EGAL;
	private int dimension;
	public static final int INF_OU_EGAL = 0;
	public static final int SUP_OU_EGAL = 1;
	private float partieDroite = 0;
	private boolean fonctionObjectif;
	private boolean maximiser;
	private String nomEquation = null;
	
	// donc par defaut on a :
	//----------------------#
	//  0       0           #
	//  - X  +  - Y <= 0    #
	//  1       1           #
	//----------------------#
	
	/**
	 * Cree une equation de dimension dimension.
	 */
	public Equation(int dimension, boolean fonctionObjectif) {
		this.dimension = dimension;
		this.fonctionObjectif = fonctionObjectif;
		
		for (int i = 0; i < dimension; i++) {
			coefficients.add(0.0f);
		}
	}
	
	/**
	 * Cree une equation de dimension dimension et de signe signe.
	 */
	public Equation(int dimension, boolean fonctionObjectif, int signe) {
		this.dimension = dimension;
		this.signe = signe;
		this.fonctionObjectif = fonctionObjectif;
		
		for (int i = 0; i < dimension; i++) {
			coefficients.add(0.0f);
		}
	}
	
	/**
	 * Permet de changer un des coefficients de l'equation.
	 * @param position La position de la modification du coefficient.
	 * @param valeur La nouvelle valeur du coefficient.
	 * @return Vrai ssi le changement de coefficient a fonctionne.
	 * @throws MauvaiseDimensionException 
	 * @throws IndiceIncorrectException 
	 */
	public void setCoefficient(int position, float valeur) throws IndiceIncorrectException {
		if (position >= 0 && position < dimension) {
			coefficients.set(position, valeur);
		}
		else throw new IndiceIncorrectException("Tentative de modification d'un coefficient d'equation en dehors des limites : "+position);
	}
	
	/**
	 * Permet d'obtenir une representation de l'equation sous forme de chaine de caractere.
	 * @return Une representation de l'equation sous forme de chaine de caractere.
	 */
	public String afficheEquation() {
		String res = "";
		boolean premier = true;
		
		if (!isFonctionObjectif()) {
			//Nom de l'equation
			if (getNomEquation() != null) res += getNomEquation() + " : ";
		}
		else if (isMaximiser()) res += "Maximiser ";
			 else res += "Minimiser ";
		
		//Coefficients de l'equation
		for (Float coef : getCoefficients()) {
			if (!premier) {
				if (coef < 0.0f) {
					res += " - " + -coef;
				}
				else res += " + " + coef;
			}
			else {
				premier = false;
				res += coef;
			}
		}
		
		if (!isFonctionObjectif()) {
			//Signe de l'equation (<=, >=, etc...)
			switch(getSigne()) {
				case INF_OU_EGAL : res += " <= "; break;
				case SUP_OU_EGAL : res += " >= "; break;
			}
			
			//Partie droite
			res += getPartieDroite();
		}
		else res += " sous les contraintes : ";
			
		return res;
	}
	
	/**
	 * Permet d'obtenir une representation de l'equation sous forme de chaine de caractere.
	 * @return Une representation de l'equation sous forme de chaine de caractere.
	 */
	public String afficheEquation(ArrayList<String> nomVariables) {
		String res = "";
		boolean premier = true;
		
		if (!isFonctionObjectif()) {
			//Nom de l'equation
			if (getNomEquation() != null) res += getNomEquation() + " : ";
		}
		else if (isMaximiser()) res += "Maximiser ";
			 else res += "Minimiser ";
		
		//Coefficients de l'equation
		int i = 0;
		for (Float coef : getCoefficients()) {
			if (!premier) {
				if (coef < 0.0f) {
					res += " - " + -coef + nomVariables.get(i);
				}
				else res += " + " + coef + nomVariables.get(i);
			}
			else {
				premier = false;
				res += coef + nomVariables.get(i);
			}
			i++;
		}
		
		if (!isFonctionObjectif()) {
			//Signe de l'equation (<=, >=, etc...)
			switch(getSigne()) {
				case INF_OU_EGAL : res += " <= "; break;
				case SUP_OU_EGAL : res += " >= "; break;
			}
			
			//Partie droite
			res += getPartieDroite();
		}
		else res += " sous les contraintes : ";
			
		return res;
	}

	/**
	 * Permet d'acceder a la valeur de la dimension.
	 * @return La valeur de la dimension de l'equation courante.
	 */
	public int getDimension() {
		return dimension;
	}

	public ArrayList<Float> getCoefficients() {
		return coefficients;
	}

	public int getSigne() {
		return signe;
	}

	public float getPartieDroite() {
		return partieDroite;
	}

	public void setPartieDroite(float partieDroite) {
		this.partieDroite = partieDroite;
	}

	public boolean isFonctionObjectif() {
		return fonctionObjectif;
	}

	public boolean isMaximiser() {
		return maximiser;
	}

	public void setMaximiser(boolean maximiser) {
		this.maximiser = maximiser;
	}

	public String getNomEquation() {
		return nomEquation;
	}

	public void setNomEquation(String nomEquation) {
		this.nomEquation = nomEquation;
	}
}
